﻿#include "JSONParse.h"

using namespace std;

CJSONParse::CJSONParse(const char* pJson/* = NULL*/)
{
	if (!pJson)
	{
		m_pJsonRoot = NULL;
	}
	else
	{
		m_pJsonRoot = cJSON_Parse(pJson);
		// if (m_pJsonRoot == NULL) {
		// 	const char *error_ptr = cJSON_GetErrorPtr();
		// 	if (error_ptr != NULL) {
		// 		printf("Error before: %s\n", error_ptr);
		// 	} else {
		// 		printf("Error: Unable to parse JSON\n");
		// 	}
		// }
//		assert(m_pJsonRoot);
	}
}

CJSONParse::~CJSONParse()
{
	if (m_pJsonRoot)
	{
		cJSON_Delete(m_pJsonRoot);
		m_pJsonRoot = NULL;
	}
}

bool CJSONParse::Load(const char* pJson)
{
	Release();
	if (!pJson)
	{
		m_pJsonRoot = NULL;
	}
	else
	{
		m_pJsonRoot = cJSON_Parse(pJson);
		assert(m_pJsonRoot);
	}

	return true;
}

bool CJSONParse::Release()
{
	if (m_pJsonRoot)
	{
		cJSON_Delete(m_pJsonRoot);
		m_pJsonRoot = NULL;
	}
	return true;
}

void CJSONParse::split(const std::string str, const std::string strPattern, std::vector<std::string>& strResultVec)
{
	std::string substring;
	std::string::size_type start = 0, index = -1;

	do
	{
		index = str.find_first_of(strPattern, start);
		if (index != std::string::npos)
		{
			substring = str.substr(start, index - start);
			strResultVec.push_back(substring);
			start = str.find_first_not_of(strPattern, index);
			if (start == std::string::npos) return;
		}
	} while (index != std::string::npos);

	substring = str.substr(start);
	strResultVec.push_back(substring);
}

cJSON* CJSONParse::GetFirstItem(const std::string& strName)
{
	if (!m_pJsonRoot)
		return NULL;

	cJSON* pJson = m_pJsonRoot;
	std::vector<std::string> strResultVec;
	CJSONParse::split(strName, std::string("/"), strResultVec);
	for (std::vector<string>::iterator strIter = strResultVec.begin(); strIter != strResultVec.end(); ++strIter)
	{
		// 过滤路径中的根节点：pXMLElement->Name() != strIter.
		if (pJson != 0 && !strIter->empty())
		{
			pJson = cJSON_GetObjectItem(pJson, strIter->c_str());
		}
	}

	if (pJson && !pJson->valuestring && pJson->type == cJSON_Object)
	{
		pJson = pJson->child;
	}

	return pJson;
}

cJSON* CJSONParse::GetNextSiblingItem(const cJSON* pItem)
{
	if (!pItem)
	{
		return NULL;
	}

	return pItem->next;
}

bool CJSONParse::GetValueStr(cJSON* pJson, const std::string& strName, std::string& strValue)
{
	strValue = "";
	if (!pJson || strName.empty())
	{
		return false;
	}

	cJSON* pItem = cJSON_GetObjectItem(pJson, strName.c_str());
	if (pItem && pItem->valuestring)
	{
		strValue = pItem->valuestring;
		return true;
	}

	while (pJson)
	{
		if (pJson->valuestring && (0 == strcmp(pJson->string, strName.c_str())))
		{
			strValue = pJson->valuestring;
			return true;
		}
		else if (pJson->next)
		{
			pJson = GetNextSiblingItem(pJson);
		}
		else
		{
			break;
		}
	}

	return false;
}

bool CJSONParse::GetValueStr(cJSON* pJson, const std::string& strName, CData& strValue)
{
	strValue = "";
	if (!pJson || strName.empty())
	{
		return false;
	}

	cJSON* pItem = cJSON_GetObjectItem(pJson, strName.c_str());
	if (pItem && pItem->valuestring)
	{
		strValue = pItem->valuestring;
		return true;
	}

	while (pJson)
	{
		if (pJson->valuestring && (0 == strcmp(pJson->string, strName.c_str())))
		{
			strValue = pJson->valuestring;
			return true;
		}
		else if (pJson->next)
		{
			pJson = GetNextSiblingItem(pJson);
		}
		else
		{
			break;
		}
	}

	return false;
}

bool CJSONParse::GetValueAuto(cJSON* pJson, const std::string& strName, CData& strValue)
{
	strValue = "";
	if (!pJson || strName.empty())
	{
		return false;
	}

	cJSON* pItem = cJSON_GetObjectItem(pJson, strName.c_str());
	if (!pItem) {
		return false;
	}

	if ((cJSON_String == pItem->type))
	{
		strValue = pItem->valuestring;
		return true;
	}
	else if ((cJSON_Number == pItem->type)) {
		strValue = pItem->valuedouble;
		return true;
	}

	while (pJson)
	{
		if (pJson->valuestring && (0 == strcmp(pJson->string, strName.c_str())))
		{
			strValue = pJson->valuestring;
			return true;
		}
		else if ((cJSON_Number == pItem->type) && (0 == strcmp(pJson->string, strName.c_str()))) {
			strValue = pJson->valuedouble;
			return true;
		}
		else if (pJson->next)
		{
			pJson = GetNextSiblingItem(pJson);
		}
		else
		{
			break;
		}
	}

	return false;
}

bool CJSONParse::GetValueNumber(cJSON* pJson, const std::string& strName, int& nValue)
{
	nValue = 0;
	if (!pJson || strName.empty())
	{
		return false;
	}

	cJSON* pItem = cJSON_GetObjectItem(pJson, strName.c_str());
	if (pItem && pItem->valueint)
	{
		nValue = pItem->valueint;
		return true;
	}

	while (pJson)
	{
		if (pJson->valueint && (0 == strcmp(pJson->string, strName.c_str())))
		{
			nValue = pJson->valueint;
			return true;
		}
		else if (pJson->next)
		{
			pJson = GetNextSiblingItem(pJson);
		}
		else
		{
			break;
		}
	}

	return false;
}

bool CJSONParse::GetValueDouble(cJSON* pJson, const std::string& strName, double& dValue)
{
	dValue = 0;
	if (!pJson || strName.empty())
	{
		return false;
	}

	cJSON* pItem = cJSON_GetObjectItem(pJson, strName.c_str());
	if (!pItem) {
		return false;
	}

	if (pItem->valuedouble)
	{
		dValue = pItem->valuedouble;
		return true;
	}

	while (pJson)
	{
		if (pJson->valuedouble && (0 == strcmp(pJson->string, strName.c_str())))
		{
			dValue = pItem->valuedouble;
			return true;
		}
		else if (pJson->next)
		{
			pJson = GetNextSiblingItem(pJson);
		}
		else
		{
			break;
		}
	}

	return false;
}

void CJSONParse::printJson(cJSON* root, std::map<std::string, std::string>& KeyValue)//以递归的方式打印json的最内层键值对
{
	for (int i = 0; i < cJSON_GetArraySize(root); i++)   //遍历最外层json键值对
	{
		cJSON* item = cJSON_GetArrayItem(root, i);
		if (cJSON_Object == item->type || cJSON_Array == item->type)      //如果对应键的值仍为cJSON_Object就递归调用printJson
			printJson(item, KeyValue);
		else                                //值不为json对象就直接打印出键和值
		{
			if (item->valuestring && item->string)
			{
				KeyValue[item->string] = item->valuestring;
			}
		}
	}
}

void CJSONParse::printJson(cJSON* root, std::map<CData, CData>& KeyValue)//以递归的方式打印json的最内层键值对
{
	for (int i = 0; i < cJSON_GetArraySize(root); i++)   //遍历最外层json键值对
	{
		cJSON* item = cJSON_GetArrayItem(root, i);
		if (cJSON_Object == item->type || cJSON_Array == item->type)      //如果对应键的值仍为cJSON_Object就递归调用printJson
			printJson(item, KeyValue);
		else                                //值不为json对象就直接打印出键和值
		{
			if (item->valuestring && item->string && cJSON_String == item->type) {
				KeyValue[item->string] = item->valuestring;
			}
			else if (cJSON_Number == item->type) {
				KeyValue[item->string] = item->valuedouble;
			}
			else if (cJSON_True == item->type || cJSON_False == item->type) {
				KeyValue[item->string] = item->valueint;
			}
		}
	}
}

const char* safeGetStringValue(cJSON* object, const char* key) {
	cJSON* item = cJSON_GetObjectItem(object, key);
	return (item != NULL && cJSON_IsString(item)) ? item->valuestring : "N/A";
}